﻿using System.Threading;
using System;

namespace TripleGame.GUI
{
    public class TimeBoundBackgroundExecutor
    {
        private Exception unhandledException;
        private int timeoutMilliseconds;

        public TimeBoundBackgroundExecutor(int timeoutMilliseconds)
        {
            this.timeoutMilliseconds = timeoutMilliseconds;
        }

        public void Execute(ThreadStart functionality)
        {
            this.unhandledException = null;

            Thread thread = new Thread(delegate()
            {
                try
                {
                    functionality();
                }
                catch (Exception ex)
                {
                    this.unhandledException = ex;
                }
                catch
                {
                    this.unhandledException = 
                        new Exception("Operation execution failed due to unexpected crash.");
                }
            });
            thread.Start();
            bool threadFinished = thread.Join(timeoutMilliseconds);

            if (! threadFinished)
            {
                // The operation exceeded its time limit -> forcefully abort it
                thread.Abort();
                throw new InvalidOperationException("Operation execution failed due to timeout.");
            }

            if (this.unhandledException != null)
            {
                throw this.unhandledException;
            }
        }
    }
}
